package com.xiumu.service.sys.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiumu.common.core.exception.dict.DictException;
import com.xiumu.common.core.page.PageQuery;
import com.xiumu.common.core.utils.AssertUtil;
import com.xiumu.dao.sys.DictDao;
import com.xiumu.pojo.sys.dto.DictDTO;
import com.xiumu.pojo.sys.dto.DictItemDTO;
import com.xiumu.pojo.sys.entity.DictEntity;
import com.xiumu.pojo.sys.entity.DictItem;
import com.xiumu.pojo.sys.query.DictQuery;
import com.xiumu.pojo.sys.vo.DictItemVO;
import com.xiumu.pojo.sys.vo.DictVO;
import com.xiumu.service.sys.DictItemService;
import com.xiumu.service.sys.DictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 字典
 *
 * @author XiuMu
 * @since 2024/12/30 21:14
 */
@Service
public class DictServiceImpl extends ServiceImpl<DictDao, DictEntity> implements DictService {

    @Autowired
    private DictItemService dictItemService;

    @Override
    public Page<DictEntity> listPage(PageQuery<DictQuery, DictEntity> pageQuery) {
        LambdaQueryWrapper<DictEntity> queryWrapper = Wrappers.lambdaQuery(DictEntity.class);
        DictQuery query = pageQuery.getCondition();
        if (Objects.nonNull(query)) {
            queryWrapper.eq(StrUtil.isNotBlank(query.getDictCode()), DictEntity::getDictCode, query.getDictCode());
            queryWrapper.likeRight(StrUtil.isNotBlank(query.getDictName()), DictEntity::getDictName, query.getDictName());
        }
        return this.page(pageQuery.toPage(), queryWrapper);
    }

    @Override
    public List<DictVO> listALl() {
        List<DictEntity> entities = this.list();
        List<DictItem> items = dictItemService.list();
        Map<String, List<DictItem>> valueMap = items.stream().collect(Collectors.groupingBy(DictItem::getDictCode));
        List<DictVO> vos = new ArrayList<>();
        for (DictEntity entity : entities) {
            DictVO dictVO = BeanUtil.copyProperties(entity, DictVO.class);
            List<DictItem> itemList = valueMap.get(entity.getDictCode());
            if (CollUtil.isNotEmpty(itemList)) {
                List<DictItemVO> dictItems = itemList.stream().map(item -> {
                    DictItemVO itemVO = BeanUtil.copyProperties(item, DictItemVO.class);
                    if (StrUtil.isNotBlank(item.getMeta())){
                        itemVO.setMetaEntity(JSONUtil.parseObj(item.getMeta()));
                    }
                    return itemVO;

                }).toList();
                dictVO.setDictItems(dictItems);
            }
            vos.add(dictVO);
        }
        return vos;
    }

    @Override
    @Transactional
    public Boolean create(DictDTO dictDTO) {
        DictEntity entity = getOne(Wrappers.lambdaQuery(DictEntity.class).eq(DictEntity::getDictCode, dictDTO.getDictCode()));
        AssertUtil.isNull(entity, DictException.DICT_EXIST);
        entity = BeanUtil.copyProperties(dictDTO, DictEntity.class);
        return save(entity);
    }

    @Override
    @Transactional
    public Boolean updateDict(Long id, DictDTO dictDTO) {
        DictEntity entity = getById(id);
        AssertUtil.isNotNull(entity, DictException.NOT_EXIST);
        entity = getOne(Wrappers.lambdaQuery(DictEntity.class).ne(DictEntity::getId, id).eq(DictEntity::getDictCode, dictDTO.getDictCode()));
        AssertUtil.isNull(entity, DictException.DICT_EXIST);
        entity = BeanUtil.copyProperties(dictDTO, DictEntity.class);
        entity.setId(id);
        return updateById(entity);
    }

    @Override
    public Boolean deleteById(Long id) {
        return removeById(id);
    }

    @Override
    @Transactional
    public Boolean createItem(Long id, DictItemDTO itemDTO) {
        DictEntity entity = getById(id);
        AssertUtil.isNotNull(entity, DictException.NOT_EXIST);
        if (StrUtil.isNotBlank(itemDTO.getMeta())){
            AssertUtil.isTrue(JSONUtil.isTypeJSON(itemDTO.getMeta()), DictException.META_NOT_JSON);
        }
        Boolean exist = dictItemService.existByDictIdAndValue(id, itemDTO.getValue());
        AssertUtil.isFalse(exist, DictException.DICT_ITEM_EXIST);
        DictItem dictItem = BeanUtil.copyProperties(itemDTO, DictItem.class);
        dictItem.setDictCode(entity.getDictCode());
        dictItem.setDictId(entity.getId());
        return dictItemService.save(dictItem);
    }

    @Override
    @Transactional
    public Boolean updateDictItem(Long id, DictItemDTO dictItemDTO) {
        DictItem entity = dictItemService.getById(id);
        AssertUtil.isNotNull(entity, DictException.NOT_EXIST);
        entity = dictItemService.getOne(Wrappers.lambdaQuery(DictItem.class)
                .ne(DictItem::getId, id)
                .eq(DictItem::getDictCode, entity.getDictCode())
                .eq(DictItem::getValue, dictItemDTO.getValue()));
        AssertUtil.isNull(entity, DictException.DICT_ITEM_EXIST);
        entity = BeanUtil.copyProperties(dictItemDTO, DictItem.class);
        entity.setId(id);
        return dictItemService.updateById(entity);
    }
}

